package com.buaa.pm.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.buaa.pm.entity.ExtractRecord;
import com.buaa.pm.entity.MarkedRecord;
import com.buaa.pm.mapper.MarkedRecordMapper;
import com.buaa.pm.model.vo.MarkedRecordVO;
import com.buaa.pm.service.MarkedRecordService;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
public class MarkedRecordServiceImpl extends ServiceImpl<MarkedRecordMapper, MarkedRecord> implements MarkedRecordService {

    @Override
    public List<MarkedRecordVO> listMarkedRecordAll() {
        List<MarkedRecordVO> markedRecordVOList = new ArrayList<>();

        QueryWrapper<MarkedRecord> queryWrapper = new QueryWrapper<>();
        List<MarkedRecord> markedRecords = list(queryWrapper.lambda().orderByDesc(MarkedRecord::getContent));

        Map<String, Map<String, Object>> recordsMap = new HashMap<>();

// 初始化数据结构
        for (MarkedRecord markedRecord : markedRecords) {
            String mofId = markedRecord.getMofId();
            String tag = markedRecord.getTag();
            if (tag.equals("Metal_Source") || tag.equals("Solvent") || tag.equals("Organic_Linker") || tag.equals("Modulator")) {
                recordsMap.computeIfAbsent(mofId, k -> new HashMap<>())
                        .computeIfAbsent(tag, k -> new ArrayList<>());
            } else {
                recordsMap.computeIfAbsent(mofId, k -> new HashMap<>())
                        .computeIfAbsent(tag, k -> new HashSet<>());
            }
        }

// 批量查询amount对应的MarkedRecord
        Set<String> amountIds = markedRecords.stream()
                .filter(markedRecord -> markedRecord.getAmount() != null)
                .map(MarkedRecord::getAmount)
                .collect(Collectors.toSet());

        Map<String, MarkedRecord> amountMap;
        if (!amountIds.isEmpty()) {
            QueryWrapper<MarkedRecord> amountQueryWrapper = new QueryWrapper<>();
            amountQueryWrapper.lambda().in(MarkedRecord::getId, amountIds);
            List<MarkedRecord> amountRecords = list(amountQueryWrapper);
            amountMap = amountRecords.stream()
                    .collect(Collectors.toMap(MarkedRecord::getId, Function.identity()));
        } else {
            amountMap = new HashMap<>();
        }

// 并行处理数据
        markedRecords.parallelStream().forEach(markedRecord -> {
            String mofId = markedRecord.getMofId();
            String tag = markedRecord.getTag();
            String content = markedRecord.getContent();
            String amount = markedRecord.getAmount();

            if (tag.equals("Metal_Source") || tag.equals("Solvent") || tag.equals("Organic_Linker") || tag.equals("Modulator")) {
                if (amount != null) {
                    MarkedRecord amountRecord = amountMap.get(amount);
                    if (amountRecord != null) {
                        Map<String, String> data = new HashMap<>();
                        data.put("precursor_name", content);
                        data.put("amount", amountRecord.getContent());
                        List<Map<String, String>> dataList = (List<Map<String, String>>) recordsMap.get(mofId).get(tag);
                        synchronized (dataList) {
                            dataList.add(data);
                        }
                    }
                }
            } else {
                HashSet<String> dataSet = (HashSet<String>) recordsMap.get(mofId).get(tag);
                synchronized (dataSet) {
                    dataSet.add(content);
                }
            }
        });

// 构建结果对象
        for (Map.Entry<String, Map<String, Object>> entry : recordsMap.entrySet()) {
            String mofId = entry.getKey();
            Map<String, Object> mofRecords = entry.getValue();

            MarkedRecordVO markedRecordVO = new MarkedRecordVO();
            markedRecordVO.setMofId(mofId);
            markedRecordVO.setParam(mofRecords);

            markedRecordVOList.add(markedRecordVO);
        }

        return markedRecordVOList;
    }

    @Override
    public MarkedRecordVO markedRecordByMofId(String mofId){
        QueryWrapper<MarkedRecord> queryWrapper = new QueryWrapper<>();
        List<MarkedRecord> markedRecords = list(queryWrapper.lambda().eq(MarkedRecord::getMofId,mofId).orderByDesc(MarkedRecord::getContent));
        // 初始化数据结构
        MarkedRecordVO markedRecordVO = new MarkedRecordVO();
        Map<String, Object> param = new HashMap<>();
        for (MarkedRecord markedRecord : markedRecords) {
            String tag = markedRecord.getTag();
            if (tag.equals("Metal_Source") || tag.equals("Solvent") || tag.equals("Organic_Linker") || tag.equals("Modulator")) {
                param.computeIfAbsent(tag, k -> new ArrayList<>());
            } else {
                param.computeIfAbsent(tag, k -> new HashSet<>());
            }
        }
        // 批量查询amount对应的MarkedRecord
        Set<String> amountIds = markedRecords.stream()
                .filter(markedRecord -> markedRecord.getAmount() != null)
                .map(MarkedRecord::getAmount)
                .collect(Collectors.toSet());

        Map<String, MarkedRecord> amountMap;
        if (!amountIds.isEmpty()) {
            QueryWrapper<MarkedRecord> amountQueryWrapper = new QueryWrapper<>();
            amountQueryWrapper.lambda().in(MarkedRecord::getId, amountIds);
            List<MarkedRecord> amountRecords = list(amountQueryWrapper);
            amountMap = amountRecords.stream()
                    .collect(Collectors.toMap(MarkedRecord::getId, Function.identity()));
        } else {
            amountMap = new HashMap<>();
        }
// 并行处理数据
        markedRecords.parallelStream().forEach(markedRecord -> {
            String tag = markedRecord.getTag();
            String content = markedRecord.getContent();
            String amount = markedRecord.getAmount();

            if (tag.equals("Metal_Source") || tag.equals("Solvent") || tag.equals("Organic_Linker") || tag.equals("Modulator")) {
                if (amount != null) {
                    MarkedRecord amountRecord = amountMap.get(amount);
                    if (amountRecord != null) {
                        Map<String, String> data = new HashMap<>();
                        data.put("precursor_name", content);
                        data.put("amount", amountRecord.getContent());
                        List<Map<String, String>> dataList = (List<Map<String, String>>) param.get(tag);
                        synchronized (dataList) {
                            dataList.add(data);
                        }
                    }
                }
            } else {
                HashSet<String> dataSet = (HashSet<String>) param.get(tag);
                synchronized (dataSet) {
                    dataSet.add(content);
                }
            }
        });
        markedRecordVO.setMofId(mofId);
        markedRecordVO.setParam(param);
        return markedRecordVO;
    }


}
